package com.touringapp.android.utils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import android.os.Environment;
import android.os.StatFs;

public final class IOUtils {
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    public static final String toString(InputStream stream) throws IOException {
        StringWriter sw = new StringWriter();
        copy(stream, sw);
        return sw.toString();
    }

    public static void copy(byte[] input, OutputStream output)
            throws IOException {
        output.write(input);
    }

    // ----------------------------------------------------------------
    // byte[] -> Writer
    // ----------------------------------------------------------------

    /**
     * Copy and convert bytes from a byte[] to chars on a Writer. The platform's
     * default encoding is used for the byte-to-char conversion.
     * 
     * @param input
     *            the byte array to read from
     * @param output
     *            the Writer to write to
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(byte[] input, Writer output) throws IOException {
        ByteArrayInputStream in = new ByteArrayInputStream(input);
        copy(in, output);
    }

    /**
     * Copy and convert bytes from a byte[] to chars on a Writer, using the
     * specified encoding.
     * 
     * @param input
     *            the byte array to read from
     * @param output
     *            the Writer to write to
     * @param encoding
     *            The name of a supported character encoding. See the IANA
     *            Charset Registry for a list of valid encoding types.
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(byte[] input, Writer output, String encoding)
            throws IOException {
        ByteArrayInputStream in = new ByteArrayInputStream(input);
        copy(in, output, encoding);
    }

    // ----------------------------------------------------------------
    // Core copy methods
    // ----------------------------------------------------------------

    /**
     * Copy bytes from an InputStream to an OutputStream.
     * 
     * @param input
     *            the InputStream to read from
     * @param output
     *            the OutputStream to write to
     * @return the number of bytes copied
     * @throws IOException
     *             In case of an I/O problem
     */
    public static int copy(InputStream input, OutputStream output)
            throws IOException {
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int count = 0;
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }

    // ----------------------------------------------------------------
    // Reader -> Writer
    // ----------------------------------------------------------------

    /**
     * Copy chars from a Reader to a Writer.
     * 
     * @param input
     *            the Reader to read from
     * @param output
     *            the Writer to write to
     * @return the number of characters copied
     * @throws IOException
     *             In case of an I/O problem
     */
    public static int copy(Reader input, Writer output) throws IOException {
        char[] buffer = new char[DEFAULT_BUFFER_SIZE];
        int count = 0;
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }

    // ----------------------------------------------------------------
    // InputStream -> Writer
    // ----------------------------------------------------------------

    /**
     * Copy and convert bytes from an InputStream to chars on a Writer. The
     * platform's default encoding is used for the byte-to-char conversion.
     * 
     * @param input
     *            the InputStream to read from
     * @param output
     *            the Writer to write to
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(InputStream input, Writer output)
            throws IOException {
        InputStreamReader in = new InputStreamReader(input);
        copy(in, output);
    }

    /**
     * Copy and convert bytes from an InputStream to chars on a Writer, using
     * the specified encoding.
     * 
     * @param input
     *            the InputStream to read from
     * @param output
     *            the Writer to write to
     * @param encoding
     *            The name of a supported character encoding. See the IANA
     *            Charset Registry for a list of valid encoding types.
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(InputStream input, Writer output, String encoding)
            throws IOException {
        InputStreamReader in = new InputStreamReader(input, encoding);
        copy(in, output);
    }

    // ----------------------------------------------------------------
    // Reader -> OutputStream
    // ----------------------------------------------------------------

    /**
     * Serialize chars from a Reader to bytes on an OutputStream, and flush the
     * OutputStream.
     * 
     * @param input
     *            the Reader to read from
     * @param output
     *            the OutputStream to write to
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(Reader input, OutputStream output)
            throws IOException {
        OutputStreamWriter out = new OutputStreamWriter(output);
        copy(input, out);
        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
        // have to flush here.
        out.flush();
    }

    // ----------------------------------------------------------------
    // String -> OutputStream
    // ----------------------------------------------------------------

    /**
     * Serialize chars from a String to bytes on an OutputStream, and flush the
     * OutputStream.
     * 
     * @param input
     *            the String to read from
     * @param output
     *            the OutputStream to write to
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(String input, OutputStream output)
            throws IOException {
        StringReader in = new StringReader(input);
        OutputStreamWriter out = new OutputStreamWriter(output);
        copy(in, out);
        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
        // have to flush here.
        out.flush();
    }

    // ----------------------------------------------------------------
    // String -> Writer
    // ----------------------------------------------------------------

    /**
     * Copy chars from a String to a Writer.
     * 
     * @param input
     *            the String to read from
     * @param output
     *            the Writer to write to
     * @throws IOException
     *             In case of an I/O problem
     */
    public static void copy(String input, Writer output) throws IOException {
        output.write(input);
    }

    public static void closeQuietly( Reader input )
    {
        if( input == null )
        {
            return;
        }

        try
        {
            input.close();
        }
        catch( IOException ioe )
        {
        }
    }

    /**
     * Unconditionally close an Writer.
     * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
     *
     * @param output A (possibly null) Writer
     */
    public static void closeQuietly( Writer output )
    {
        if( output == null )
        {
            return;
        }

        try
        {
            output.close();
        }
        catch( IOException ioe )
        {
        }
    }

    /**
     * Unconditionally close an OutputStream.
     * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
     * @param output A (possibly null) OutputStream
     */
    public static void closeQuietly( OutputStream output )
    {
        if( output == null )
        {
            return;
        }

        try
        {
            output.close();
        }
        catch( IOException ioe )
        {
        }
    }

    /**
     * Unconditionally close an InputStream.
     * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
     * @param input A (possibly null) InputStream
     */
    public static void closeQuietly( InputStream input )
    {
        if( input == null )
        {
            return;
        }

        try
        {
            input.close();
        }
        catch( IOException ioe )
        {
        }
    }
    
    public static double getFreeMegabytes(){
		return (double)getFreeBytes() / 1048576; 
    }

    public static long getFreeBytes(){
		StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath()); 
		return (long)stat.getBlockSize() * stat.getBlockCount(); 
    }

}
